﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Threading;

using log4net;
using PriceLibrary.Utilities;
using PriceLibrary.PriceService;


namespace VDataAdapter.PriceServerAdapter
{
    class PriceServerConnector
    {
        private static ILog _log = LogManager.GetLogger(typeof(PriceServerConnector));
        private ClientManager _clientManager;
        private PriceCallBack _priceCallBack;
        private PriceServerEventAdapter _psEventAdapter;
        private IPriceServerEventHandler _handler;
        private ChartCallBack _chartCallBack;
        private bool _listening;

        private void Init(string priceURI, string chartURI)
        {
            //_clientManager = new ClientManager(priceURI);
            // _priceCallBack = _clientManager.CreateCallBackWithService();
            _priceCallBack = new PriceCallBack(priceURI);
            _chartCallBack = new ChartCallBack(chartURI);
            
            _psEventAdapter = new PriceServerEventAdapter(_handler);

            InitEventHandler();
             

        }

        private void InitEventHandler()
        {
            //Inits delegate for PriceClient                                
            _priceCallBack.EndSendStockData += _psEventAdapter.GetFirstTime;
            _priceCallBack.Top3PriceChanged += _psEventAdapter.Top3PricesStock_Changed;
            _priceCallBack.PriceServer.GetTickersByFloorCode(100);
            _priceCallBack.EndReceivedNewTickers += NewTickersReceived;

            _priceCallBack.MarketInfoChanged += _psEventAdapter.MarketInfoChanged;
            _priceCallBack.EndReceivedPtTopPrices += _psEventAdapter.PutThroughChanged;
            _priceCallBack.EndReceivedPtTransactions += _psEventAdapter.PutThroughTransactionChanged;

            ////Transaction service!
            _chartCallBack.ChartService.SubscribeSymbols(new List<string>());
            _chartCallBack.EndReceivedAllTransaction += _psEventAdapter.Transactions_Changed;
        }

        public void UnRegisterPriceService()
        {
            _priceCallBack.EndSendStockData -= _psEventAdapter.GetFirstTime;
            _priceCallBack.Top3PriceChanged -= _psEventAdapter.Top3PricesStock_Changed;

            _priceCallBack.EndReceivedNewTickers -= NewTickersReceived;

            _priceCallBack.MarketInfoChanged -= _psEventAdapter.MarketInfoChanged;
            _priceCallBack.EndReceivedPtTopPrices -= _psEventAdapter.PutThroughChanged;
            _priceCallBack.EndReceivedPtTransactions -= _psEventAdapter.PutThroughTransactionChanged;

            _chartCallBack.EndReceivedAllTransaction -= _psEventAdapter.Transactions_Changed;

            _listening = false;
        }

        /// <summary>
        /// Pinging for reconnection if price server is down
        /// </summary>
        public void Ping()
        {
            while (_listening)
            {
                try
                {
                    _log.InfoFormat("Ping Price Server at {0}", DateTime.Now.ToString());
                    if (((ICommunicationObject)_priceCallBack.PriceServer).State == CommunicationState.Faulted)
                    {
                        Thread.Sleep(500);
                        _log.ErrorFormat("CommunicationState.Faulted State at {0}", DateTime.Now.ToString());
                        throw new VDataPSEventAdapterException("Error connecting to Price Server", null);
                        // _priceCallBack.PriceServer = _ClientManager.CreatePriceServer(_PriceCallBack);
                    }
                    // _PriceCallBack.PriceServer.SubscribeNewSymbols(new List<string>());
                }
                catch (Exception ex)
                {
                    _log.Error("Error PriceCallBackPing", ex);
                    _listening = false;
                    throw new VDataPSEventAdapterException("Error pinging to Price Server", ex);
                }
            }
        }
        /// <summary>
        /// Add symbols of market to newtickers
        /// </summary>
        /// <param name="newtickers"></param>
        /// <returns></returns>
        private IList<string> AddMarketTickers(IList<string> newtickers)
        {
            if (!newtickers.Contains("HOSE"))
                newtickers.Add("HOSE");
            if (!newtickers.Contains("HNX"))
                newtickers.Add("HNX");
            if (!newtickers.Contains("UPCOM"))
                newtickers.Add("UPCOM");
            if (!newtickers.Contains("VN30"))
                newtickers.Add("VN30");
            if (!newtickers.Contains("HNX30"))
                newtickers.Add("HNX30");

            return newtickers;
        }
        private void NewTickersReceived(IList<string> newtickers)
        {
            try
            {
                if (_priceCallBack != null)
                {

                    foreach (string newticker in newtickers)
                    {
                        _priceCallBack.Tickers.Add(newticker);
                    }

                    //Đăng ký lên server!
                    _priceCallBack.PriceServer.SubscribeNewSymbols(newtickers as List<string>);

                    newtickers = AddMarketTickers(newtickers);
                    //Dang ky Transactions Service
                    _chartCallBack.ChartService.SubscribeAllSymbols(newtickers as List<string>);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error New Tickers Received", ex);
            }
        }
    }
}
